﻿Imports System
Imports System.Diagnostics
Imports System.Threading
Imports System.Collections
Imports System.IO
Imports System.Management
Imports System.Configuration
Imports System.Collections.Specialized
Imports System.Data.SqlClient

Module Module1
    Sub Main()
        Dim appSettings As NameValueCollection = ConfigurationManager.AppSettings
        Dim ThreadSleep As Integer
        Dim DbComm As New SqlCommand
        Dim PcList As New List(Of Diagnostics.PerformanceCounter)
        Dim PcDeltaList As New List(Of Diagnostics.PerformanceCounter)

        EventLog.WriteEntry("Application", "PerformanceCounter started.")
        Console.WriteLine("PerformanceCounter started.")

        'Grab the time to sleep between polling passes from the app.config.
        If IsNumeric(appSettings.Item("SleepTimeMillisecions")) Then
            ThreadSleep = appSettings.Item("SleepTimeMillisecions")
        Else
            ThreadSleep = 60000
        End If

        While 1 = 1
            PcList.Clear()
            PcDeltaList.Clear()
            'Build counter list and baseline delta type counters.
            For Each setting In ConfigurationManager.AppSettings.AllKeys
                If setting.ToString().Contains("PerfMon") Then
                    Dim ServerName As String = appSettings.Item(setting.ToString()).Split(";")(0)
                    Dim CategoryName As String = appSettings.Item(setting.ToString()).Split(";")(1)
                    Dim CounterName As String = appSettings.Item(setting.ToString()).Split(";")(2)
                    Dim DeltaCounter As String = appSettings.Item(setting.ToString()).Split(";")(3)
                    Dim InstanceFilter As String = appSettings.Item(setting.ToString()).Split(";")(4)
                    Dim PcCat As New PerformanceCounterCategory(CategoryName, ServerName)
                    If PcCat.GetInstanceNames.Count = 0 Then
                        'Add counter to list that does not contain instances
                        Dim Pc As New Diagnostics.PerformanceCounter(CategoryName, CounterName)
                        Pc.MachineName = ServerName
                        If DeltaCounter <> "1" Then
                            PcList.Add(Pc)  'Add counter that is a point in time snapshot
                        Else
                            PcDeltaList.Add(Pc) 'Add counter that is a delta type e.g. % CPU Utilization or rates like requests/sec
                            PollAndLogCounter(Nothing, Pc) 'Baseline the delta counter so the next call returns a non-zero value
                        End If
                    Else
                        'Add counter to list that contains instances
                        Dim FilterHit As Boolean = False
                        For Each Instance In New PerformanceCounterCategory(CategoryName, ServerName).GetInstanceNames
                            FilterHit = False
                            Dim Pc As New Diagnostics.PerformanceCounter(CategoryName, CounterName, Instance, ServerName)
                            'If a filter string was specified, does it match
                            If InstanceFilter.Length = 0 Then
                                FilterHit = True
                            ElseIf Instance.ToString().Contains(InstanceFilter) Then
                                FilterHit = True
                            End If
                            If FilterHit Then
                                If DeltaCounter <> "1" Then
                                    PcList.Add(Pc)  'Add counter that is a point in time snapshot
                                Else
                                    PcDeltaList.Add(Pc) 'Add counter that is a delta type e.g. % CPU Utilization or rates like requests/sec
                                    PollAndLogCounter(Nothing, Pc) 'Baseline the delta counter so the next call returns a non-zero value
                                End If
                            End If
                        Next
                    End If
                End If
            Next

            Thread.Sleep(ThreadSleep)   'Sleep between polls

            Using Dbconn As New SqlConnection(ConfigurationManager.ConnectionStrings("DbRepository").ToString())
                'Poll and log counters
                For Each Pc In PcDeltaList
                    PollAndLogCounter(Dbconn, Pc)
                Next
                For Each Pc In PcList
                    PollAndLogCounter(Dbconn, Pc)
                Next

                'Compress Data into Dw Model
                Try
                    DbComm.Connection = Dbconn
                    DbComm.CommandType = CommandType.StoredProcedure
                    DbComm.CommandText = ConfigurationManager.AppSettings.Item("DwImportProc")
                    DbComm.Parameters.Clear()
                    DbComm.Connection.Open()
                    DbComm.ExecuteNonQuery()
                    DbComm.Connection.Close()
                Catch ex As Exception
                    EventLog.WriteEntry("Application", "DwImportProc failed.  " & ex.ToString())
                    Console.WriteLine("DwImportProc failed.  " & ex.ToString())
                End Try
            End Using
        End While
    End Sub

    Sub PollAndLogCounter(ByVal Dbconn As SqlConnection, ByRef Pc As Diagnostics.PerformanceCounter)
        If Dbconn Is Nothing Then
            Try
                Pc.NextValue()
            Catch ex As Exception
                If ex.HResult <> -2146233079 Then
                    Console.WriteLine(ex.HResult)
                    Console.WriteLine(ex.ToString())
                    EventLog.WriteEntry("Application", ex.ToString())
                End If
            End Try
        Else
            Try
                Dim DbComm As New SqlCommand
                DbComm.Connection = Dbconn
                DbComm.CommandType = CommandType.StoredProcedure
                DbComm.CommandText = ConfigurationManager.AppSettings.Item("CounterInsertProc")
                DbComm.Parameters.Clear()
                DbComm.Parameters.Add("@ServerName", SqlDbType.VarChar, 100).Value = Pc.MachineName.ToString()
                DbComm.Parameters.Add("@CategoryName", SqlDbType.VarChar, 100).Value = Pc.CategoryName.ToString()
                DbComm.Parameters.Add("@InstanceName", SqlDbType.VarChar, 500).Value = Pc.InstanceName.ToString()
                DbComm.Parameters.Add("@CounterName", SqlDbType.VarChar, 100).Value = Pc.CounterName()
                DbComm.Parameters.Add("@Value", SqlDbType.Float).Value = Pc.NextValue()
                DbComm.Connection.Open()
                DbComm.ExecuteNonQuery()
                DbComm.Connection.Close()
            Catch ex As Exception
                If ex.HResult <> -2146233079 Then
                    Console.WriteLine(ex.HResult)
                    Console.WriteLine(ex.ToString())
                    EventLog.WriteEntry("Application", ex.ToString())
                End If
            End Try
        End If
    End Sub
End Module
